package util;

import org.apache.commons.io.FileUtils;
import org.json.JSONArray;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class Tools {
    private static JSONObject id2name;
    private static JSONObject name2id;

    /**
     * 在新建实例时从配置文件中读取站点及其代码信息
     */
    public Tools() {
        try {
            String url = this.getClass().getResource("").getPath().replaceAll("%20", " ");
            String path = url.substring(0, url.indexOf("WEB-INF"));
            String input = FileUtils.readFileToString(new File(path + "WEB-INF/static/data/old/" +
                    "siteNames.json"), "UTF-8");
            id2name = new JSONObject(input);
            input = FileUtils.readFileToString(new File(path + "WEB-INF/static/data/old/" +
                    "reversedSitenames.json"), "UTF-8");
            name2id = new JSONObject(input);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public JSONObject getId2name() {
        return id2name;
    }

    public JSONObject getName2id() {
        return name2id;
    }

    /**
     * 获取当前日期的时间戳，单位秒
     *
     * @param date
     * @return String
     */
    public String getTimeStamp(Date date) {
        return String.valueOf(date.getTime() / 1000);
    }

    /**
     * 将当前时间按指定的格式输出
     *
     * @param date   指定的日期
     * @param format 指定的格式，如"yyyy-MM-dd"
     * @return String
     */
    public String formatDate(Date date, String format) {
        SimpleDateFormat df = new SimpleDateFormat(format);
        return df.format(date);
    }

    /**
     * 将类似于November 11. 2018格式的日期进行解析
     *
     * @param time
     * @return
     */
    public Date parseDate(String time) {
        System.out.println(time);
        Date date = new Date();
        try {
            SimpleDateFormat dateFormat = new SimpleDateFormat("MMMM dd, yyyy", Locale.US);
            date = dateFormat.parse(time);
        } catch (ParseException e) {
            System.out.println("Unable to parse " + e.getMessage());
        }
        return date;
    }

    /**
     * 获取当前时间的前一时刻
     *
     * @param interval 时间间隔，值可以是Calendar.DAY_OF_YEAR和Calendar.HOUR_OF_DAY，分别表示获取前一天和前一小时的时间
     */
    public Date getCurrentTime(int interval) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(interval, -1);
        String pattern = null;
        if (interval == Calendar.HOUR_OF_DAY) {
            pattern = "yyyy-MM-dd HH:00:00";
        } else if (interval == Calendar.DAY_OF_YEAR) {
            pattern = "yyyy-MM-dd";
        }
        SimpleDateFormat df = new SimpleDateFormat(pattern);
        Date end = null;
        try {
            end = df.parse(df.format(calendar.getTime()));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return end;
    }

    /**
     * @param end      当前时间的前一时刻，若当前时间为18:40:20, 则end应为17:00:00, 日期类似
     * @param interval 时间间隔是小时还是天
     */
    public Date getStartTime(Date end, int interval) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(end);
        if (interval == Calendar.HOUR_OF_DAY) {
            calendar.add(Calendar.HOUR_OF_DAY, -23);
            return calendar.getTime();
        } else if (interval == Calendar.DAY_OF_YEAR) {
            calendar.add(Calendar.DAY_OF_YEAR, -6);
            return calendar.getTime();
        } else {
            return null;
        }
    }

    /**
     * 从后台获取数据，每个请求是一个线程，返回结果是个map，key是时间，value是对应的数据
     * 获取包括start和end起止时间的数据
     */
    public HashMap<String, String> acquireData(String baseUrl, Date start, Date end, int interval, String site,
                                                   String goodsType, String staffId) {
        List<FutureTask<String>> fts = new ArrayList<FutureTask<String>>();
        List<String> dates = new ArrayList<String>();

        String format;
        int step;
        if (interval == Calendar.DAY_OF_YEAR) {
            format = "MM.dd";
            step = 1;
        }
        else if (interval == Calendar.HOUR_OF_DAY) {
            format = "MM月dd日 HH时";
            step = 1;
        }
        else {
            format = "MM-dd HH:mm:ss";
            step = 1;
        }

        Date curDate = start;
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(curDate);
        while (true) {
            calendar.add(interval, step);
            Date tempEnd = calendar.getTime();
            if (curDate.after(end)) {
                break;
            }
            String startTimestamp = getTimeStamp(curDate);
            String endTimestamp = getTimeStamp(tempEnd);

            String url = baseUrl + "siteId=" + site + "&start=" + startTimestamp + "&end=" + endTimestamp;
            if (goodsType != null) {
                url += "&goodstype=" + goodsType;
            }
            if (staffId != null) {
                url += "&scanMan=" + staffId;
            }
            DataRequest dataRequest = new DataRequest(url);
            FutureTask<String> ft = new FutureTask<String>(dataRequest);
            new Thread(ft, url).start();
            fts.add(ft);
            dates.add(formatDate(curDate, format));
            curDate = tempEnd;
        }
        HashMap<String, String> result = new HashMap<String, String>();
        for (int i = 0; i < fts.size(); i++) {
            try {
                String temp = fts.get(i).get();
                result.put(dates.get(i), temp);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 从后台获取数据，每个请求是一个线程，返回结果是个list，每个元素是map, key是时间，value是对应的数据
     * 获取包括start和end起止时间的数据
     */
    public ArrayList<HashMap<String, String>> acquireMultiData(ArrayList<String> baseUrl, Date start, Date end, int interval,
                                                               String site, String goodsType, String staffId) {
        List<FutureTask<String>> fts = new ArrayList<FutureTask<String>>();
        List<String> dates = new ArrayList<String>();

        String format = "MM.dd";
        int step = 1;
        int mapSize = 7;
        if (interval == Calendar.DAY_OF_YEAR) {
            format = "MM.dd";
            step = 1;
            mapSize = 7;
        }
        else if (interval == Calendar.HOUR_OF_DAY) {
            format = "MM月dd日 HH时";
            step = 1;
            mapSize = 24;
        }

        for(int i = 0; i < baseUrl.size(); i++) {
            Date curDate = start;
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(curDate);
            while (true) {
                calendar.add(interval, step);
                Date tempEnd = calendar.getTime();
                if (curDate.after(end)) {
                    break;
                }
                String startTimestamp = getTimeStamp(curDate);
                String endTimestamp = getTimeStamp(tempEnd);

                String url = baseUrl.get(i) + "siteId=" + site + "&start=" + startTimestamp + "&end=" + endTimestamp;
                if (goodsType != null) {
                    url += "&goodstype=" + goodsType;
                }
                if (staffId != null) {
                    url += "&scanMan=" + staffId;
                }
                DataRequest dataRequest = new DataRequest(url);
                FutureTask<String> ft = new FutureTask<String>(dataRequest);
                new Thread(ft, url).start();
                fts.add(ft);
                dates.add(formatDate(curDate, format));
                curDate = tempEnd;
            }
        }

        ArrayList<HashMap<String, String>> result = new ArrayList<HashMap<String, String>>();
        HashMap<String, String> tempResult = new HashMap<String, String>();
        for (int i = 0; i < fts.size(); i++) {
            try {
                if(i == mapSize) {
                    result.add(tempResult);
                    tempResult = new HashMap<String, String>();
                }
                String temp = fts.get(i).get();
                tempResult.put(dates.get(i), temp);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        result.add(tempResult);
        return result;
    }

    /**
     * 从后台获取数据，每个请求是一个线程，返回结果是个map，key是时间，value是对应的数据
     * 获取包括start和end起止时间的数据
     */
    public ArrayList<String> acquireTypeData(String baseUrl, Date start, Date end, String site, int typeLen) {
        List<FutureTask<String>> fts = new ArrayList<FutureTask<String>>();
        String startTimestamp = getTimeStamp(start);
        String endTimestamp = getTimeStamp(end);

        for(int i = 0; i < typeLen; i++) {
            String url = baseUrl + "startId=" + site + "&start=" + startTimestamp + "&end=" + endTimestamp +
                    "&serviceType=" + i;
            DataRequest dataRequest = new DataRequest(url);
            FutureTask<String> ft = new FutureTask<String>(dataRequest);
            fts.add(ft);
            new Thread(ft, url).start();
        }

        ArrayList<String> result = new ArrayList<String>();
        for (int i = 0; i < fts.size(); i++) {
            try {
                result.add(fts.get(i).get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    public JSONArray request(String url) {
        String result = "";
        BufferedReader in = null;
        JSONArray json = null;
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection connection = realUrl.openConnection();
            // 建立实际的连接
            connection.connect();
            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(
                    connection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
            json = new JSONArray(result);
        } catch (Exception e) {
            System.out.println("发送GET请求出现异常！" + e);
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return json;
    }

    public ArrayList<String> request(ArrayList<String> urls) {
        List<FutureTask<String>> fts = new ArrayList<FutureTask<String>>();
        ArrayList<String> results = new ArrayList<String>();
        for (int i = 0; i < urls.size(); i++) {
            String url = urls.get(i);
            DataRequest dataRequest = new DataRequest(url);
            FutureTask<String> ft = new FutureTask<String>(dataRequest);
            new Thread(ft, url).start();
            fts.add(ft);
        }

        for (int i = 0; i < fts.size(); i++) {
            try {
                results.add(fts.get(i).get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        return results;
    }
}
